package com.cloudsea.yunhaistores.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cloudsea.yunhaistores.entity.MerchantUsers;
import com.cloudsea.yunhaistores.entity.OrderItems;
import com.cloudsea.yunhaistores.entity.PaymentOrders;
import com.cloudsea.yunhaistores.entity.Tables;
import com.cloudsea.yunhaistores.mapper.MerchantUsersMapper;
import com.cloudsea.yunhaistores.mapper.OrderItemsMapper;
import com.cloudsea.yunhaistores.mapper.PaymentOrdersMapper;
import com.cloudsea.yunhaistores.mapper.TablesMapper;
import com.cloudsea.yunhaistores.service.MerchantOrderService;
import com.cloudsea.yunhaistores.vo.OrderDetailVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MerchantOrderServiceImpl implements MerchantOrderService {

    @Autowired private PaymentOrdersMapper paymentOrdersMapper;
    @Autowired private OrderItemsMapper orderItemsMapper;
    @Autowired private TablesMapper tablesMapper;
    @Autowired
    private MerchantUsersMapper merchantUsersMapper;

    @Override
    public List<OrderDetailVO> listNewOrders(Long storeId) {
        // 1. 查询该门店下所有履约状态为 1 (制作中) 的主订单
        QueryWrapper<PaymentOrders> orderWrapper = new QueryWrapper<>();
        orderWrapper.eq("store_id", storeId)
                .eq("fulfillment_status", 1)
                .orderByAsc("created_at");
        List<PaymentOrders> newOrders = paymentOrdersMapper.selectList(orderWrapper);

        if (CollectionUtils.isEmpty(newOrders)) {
            return Collections.emptyList();
        }

        // 2. 一次性批量查询所有订单的详情
        List<Long> orderIds = newOrders.stream().map(PaymentOrders::getId).collect(Collectors.toList());
        QueryWrapper<OrderItems> itemWrapper = new QueryWrapper<>();
        itemWrapper.in("order_id", orderIds);
        List<OrderItems> allItems = orderItemsMapper.selectList(itemWrapper);
        Map<Long, List<OrderItems>> itemsMap = allItems.stream()
                .collect(Collectors.groupingBy(OrderItems::getOrderId));

        // 3. 提取所有订单关联的桌台ID (去重)
        List<Long> tableIds = newOrders.stream()
                .map(PaymentOrders::getTableId)
                .filter(id -> id != null) // 过滤掉可能为空的tableId
                .distinct()
                .collect(Collectors.toList());

        Map<Long, Tables> tablesMap = Collections.emptyMap();
        if (!CollectionUtils.isEmpty(tableIds)) {
            // a. 一次性批量查询所有相关的桌台信息
            List<Tables> tablesList = tablesMapper.selectBatchIds(tableIds);
            // b. 将桌台列表转换为Map，方便快速查找
            tablesMap = tablesList.stream().collect(Collectors.toMap(Tables::getId, table -> table));
        }

        // 4. 组装成VO列表
        final Map<Long, Tables> finalTablesMap = tablesMap; // 在lambda表达式中使用，需要是final
        return newOrders.stream().map(order -> {
            OrderDetailVO vo = new OrderDetailVO();
            BeanUtils.copyProperties(order, vo);
            vo.setItems(itemsMap.getOrDefault(order.getId(), Collections.emptyList()));

            // 【核心新增逻辑】设置桌台名称
            if (order.getTableId() != null) {
                Tables table = finalTablesMap.get(order.getTableId());
                if (table != null) {
                    vo.setTableName(table.getTableName());
                } else {
                    vo.setTableName("桌台信息丢失");
                }
            } else {
                // 处理外卖或自取等没有桌台号的订单
                vo.setTableName(order.getOrderType());
            }

            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public void markAsReadyForPickup(Long orderId) {
        // 1. 查询订单
        PaymentOrders order = paymentOrdersMapper.selectById(orderId);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }

        // 2. 【安全校验】检查操作员是否有权限操作此订单
        //    这个逻辑与我们之前为“清台”写的权限校验完全一样
        long loginId = StpUtil.getLoginIdAsLong();
        MerchantUsers currentUser = merchantUsersMapper.selectById(loginId);
        if (currentUser == null || !currentUser.getMerchantId().equals(order.getMerchantId())) {
            throw new SecurityException("无权操作不属于自己商户的订单");
        }

        // 3. 校验订单的当前状态
        //    只有“制作中”的订单才能被标记为“备餐完成”
        if (order.getFulfillmentStatus() != 1) {
            throw new IllegalStateException("订单当前状态不是“制作中”，无法执行此操作");
        }

        // 4. 更新履约状态
        order.setFulfillmentStatus(2); // 状态更新为 2:待取餐/待配送

        // 5. 保存回数据库
        paymentOrdersMapper.updateById(order);

        // TODO: 发送WebSocket消息给用户小程序：“您的餐品已备好，请凭取餐号 xxx 前来取餐！”如果有电子叫号屏，在这里更新屏幕显示。
        // 6. 【后续扩展点】
        //    - 发送WebSocket消息给用户小程序：“您的餐品已备好，请凭取餐号 xxx 前来取餐！”
        //    - 如果有电子叫号屏，在这里更新屏幕显示。
    }

    @Override
    public void completeOrder(Long orderId) {
        // 1. 查询订单
        PaymentOrders order = paymentOrdersMapper.selectById(orderId);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }

        // 2. 【安全校验】检查操作员是否有权操作此订单
        //    (这个校验逻辑与 markAsReadyForPickup 方法中的完全一致)
        long loginId = StpUtil.getLoginIdAsLong();
        MerchantUsers currentUser = merchantUsersMapper.selectById(loginId);
        if (currentUser == null || !currentUser.getMerchantId().equals(order.getMerchantId())) {
            throw new SecurityException("无权操作不属于自己商户的订单");
        }

        // 3. 校验订单的当前状态
        //    只有“待取餐”的订单才能被手动“完成”
        if (order.getFulfillmentStatus() != 2) {
            // 如果订单已经是“制作中”或“已完成”，则不允许重复操作
            throw new IllegalStateException("订单当前不是“待取餐”状态，无法完成");
        }

        // 4. 更新履约状态
        order.setFulfillmentStatus(3); // 状态更新为 3:已完成

        // 5. 保存回数据库
        paymentOrdersMapper.updateById(order);

        // 6. todo 触发“订单已完成”的事件，例如：将此订单信息推送到数据分析系统。如果有会员积分功能，在这里为用户增加积分。
        //    - 在这里可以触发“订单已完成”的事件，例如：
        //    - a. 将此订单信息推送到数据分析系统。
        //    - b. 如果有会员积分功能，在这里为用户增加积分。
    }
}
